export enum RuntimeMode {
  DEV  = 'dev',
  PROD = 'prod',
}

/**
 * 运行时别名
 */
const RuntimeModeAliases: Record<string, RuntimeMode> = {
  dev        : RuntimeMode.DEV,
  devel      : RuntimeMode.DEV,
  development: RuntimeMode.DEV,
  prod       : RuntimeMode.PROD,
  production : RuntimeMode.PROD,
};

/**
 * 过滤各种运行模式的别名，转化为 RuntimeMode
 *
 * @param runtime
 */
export const filterRuntimeMode = (runtime: string): RuntimeMode =>
  ((runtime != null && runtime !== '') && RuntimeModeAliases[runtime] || RuntimeMode.DEV);

/**
 * 项目基础信息
 */
export type ProjectBasicInfo = {
  /**
   * 项目名称
   */
  project: string,
  /**
   * 平台
   */
  platform: string,
  /**
   * 运行模式
   */
  mode: RuntimeMode,
  /**
   * 自定义环境标示
   */
  custom: string,
}

/**
 * 解析 npm run 的指令，转化为项目的环境变量
 *
 * @example
 * npm run project-name:weapp:dev:user-name
 *
 * @param cmd
 */
export const parseNpmCommand = (cmd: string): ProjectBasicInfo => {
  const [project, platform, mode, custom] = cmd.split(/:/);

  return {
    project,
    platform,
    mode  : filterRuntimeMode(mode),
    custom: custom == null ? '' : custom,
  };
};

export type ProjectInfoEnvProps = NodeJS.ProcessEnv & {
  npm_lifecycle_event?: string,
  TARO_ENV?: string,
  MODE?: string,
  CUSTOM?: string,
  PROJECT?: string,
}

/**
 * 从 Node 运行环境变量提取所需的项目基础信息
 *
 * @param env node 运行时的 process.env
 */
export const extractProjectInfo = (env?: ProjectInfoEnvProps): ProjectBasicInfo => {
  env = env || process.env;
  // 不使用 NODE_ENV 而使用 自定义变量 MODE
  const { npm_lifecycle_event } = env;
  const vars: ProjectBasicInfo = {
    project : '',
    mode    : RuntimeMode.DEV,
    custom  : '',
    platform: '',
  };

  // 混入 npm run command 的内容
  if (npm_lifecycle_event != null && npm_lifecycle_event !== '') {
    Object.assign(vars, parseNpmCommand(npm_lifecycle_event));
  }

  // 如果指令的参数有补充的内容，继续 mixin ProjectBasicInfo
  const { TARO_ENV, MODE, CUSTOM, PROJECT } = env;

  if (TARO_ENV != null && TARO_ENV !== '') {
    vars.platform = TARO_ENV;
  }
  if (PROJECT != null && PROJECT !== '') {
    vars.project = PROJECT;
  }
  if (MODE != null && MODE !== '') {
    vars.mode = filterRuntimeMode(MODE);
  }
  if (CUSTOM != null && MODE !== '') {
    vars.custom = CUSTOM;
  }

  return vars;
};
